/**
 * @PROJECT 
 * @DATE 2018年7月9日 下午3:40:31
 * @AUTHOR LUYU
 */
package com.kool.tlwp.generator;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kool.tlwp.bean.IoFieldVo;
import com.kool.tlwp.exception.AppException;
import com.kool.tlwp.generator.context.BusinessContext;
import com.kool.tlwp.util.DateUtils;
import com.kool.tlwp.util.FileUtils;
import com.kool.tlwp.util.PropertyUtils;
import com.kool.tlwp.util.StringUtils;

import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * @DESCRIBE 业务处理类生成工具
 * @AUTHOR LUYU
 * @DATE 2018年7月9日 下午3:40:31
 *
 */
public class BusinessCodeGenerator extends CodeGenerator {

	/**
	 * @throws AppException
	 */
	public BusinessCodeGenerator(BusinessContext context) throws AppException {
		super(context);
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午3:40:41
	 *
	 * @throws AppException
	 */
	@Override
	public void generate() throws AppException {
		BusinessContext BC = (BusinessContext) context;
		String destDir = BC.getDestDir() + "\\"
				+ DateUtils.getCurrentTimeString(DateUtils.FORMAT_DATE_AND_TIME_WITHOUT_SPLIT);
		String name = BC.getBusinessName();
		String lowName = name.substring(0, 1).toLowerCase() + name.substring(1);
		String pkg = BC.getPkg();
		String actionDir = getActionDir(destDir, pkg, lowName);
		String serviceDir = getServiceDir(destDir, pkg);
		String ioDir = getIoDir(destDir, pkg, lowName);
		try {
			// AddAction
			Template template = configuration.getTemplate("AddAction.ftl");
			template.setOutputEncoding("UTF-8");
			HashMap<String, Object> map = getAddActionMap(BC, lowName);
			Writer writer = getAddActionWriter(name, actionDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
			// UpdateAction
			template = configuration.getTemplate("UpdateAction.ftl");
			template.setOutputEncoding("UTF-8");
			map = getUpdateActionMap(BC, lowName);
			writer = getUpdateActionWriter(name, actionDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
			// DeleteAction
			template = configuration.getTemplate("DeleteAction.ftl");
			template.setOutputEncoding("UTF-8");
			map = getDeleteActionMap(BC, lowName);
			writer = getDeleteActionWriter(name, actionDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
			// QueryAction
			template = configuration.getTemplate("QueryAction.ftl");
			template.setOutputEncoding("UTF-8");
			map = getQueryActionMap(BC, lowName);
			writer = getQueryActionWriter(name, actionDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
			// QueryPageAction
			template = configuration.getTemplate("QueryPageAction.ftl");
			template.setOutputEncoding("UTF-8");
			map = getQueryPageActionMap(BC, lowName);
			writer = getQueryPageActionWriter(name, actionDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
			// Service
			template = configuration.getTemplate("Service.ftl");
			template.setOutputEncoding("UTF-8");
			map = getServiceMap(BC);
			writer = getServiceWriter(name, serviceDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
			// IO
			genIo(BC, lowName, ioDir, BC.getAddIn());
			genIo(BC, lowName, ioDir, BC.getUpdateIn());
			genIo(BC, lowName, ioDir, BC.getDeleteIn());
			genIo(BC, lowName, ioDir, BC.getQueryIn());
			genIo(BC, lowName, ioDir, BC.getQueryOut());

		} catch (IOException e) {
			throw new AppException("操作Template文件错误!", e);
		} catch (TemplateException e) {
			throw new AppException("操作Template文件错误!", e);
		} catch (Exception e) {
			throw new AppException("工具发生错误!", e);
		}
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月10日 上午10:41:57
	 *
	 * @param BC
	 * @param ioDir
	 * @param ioName
	 * @throws AppException
	 */
	private void genIo(BusinessContext BC, String lowName, String ioDir, String ioName) throws AppException {
		try {
			Template template = configuration.getTemplate("IO.ftl");
			template.setOutputEncoding("UTF-8");
			HashMap<String, Object> map = getIoMap(BC, lowName, ioName);
			Writer writer = getIoWriter(ioName, ioDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new AppException("操作Template文件错误!", e);
		} catch (TemplateException e) {
			e.printStackTrace();
			throw new AppException("操作Template文件错误!", e);
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException("工具发生错误!", e);
		}
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月10日 上午9:51:55
	 *
	 * @param ioName
	 * @param ioDir
	 * @return
	 * @throws IOException
	 */
	private Writer getIoWriter(String ioName, String ioDir) throws IOException {
		String fileName = ioName + "Bean.java";
		String destPath = ioDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月10日 上午9:51:53
	 *
	 * @param BC
	 * @param lowName
	 * @param ioName
	 * @return
	 * @throws Exception 
	 */
	private HashMap<String, Object> getIoMap(BusinessContext BC, String lowName, String ioName) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("name", lowName);
		map.put("ioName", ioName);
		List<IoFieldVo> list = json2IoVoList(ioName);
		map.put("ioFields", list);
		return map;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:16:15
	 *
	 * @param clazzName
	 * @param actionDir
	 * @return
	 * @throws IOException
	 */
	private Writer getServiceWriter(String clazzName, Object actionDir) throws IOException {
		String fileName = clazzName + "Service.java";
		String destPath = actionDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:16:13
	 *
	 * @param BC
	 * @return
	 */
	private HashMap<String, Object> getServiceMap(BusinessContext BC) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("upTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), true));
		map.put("lowTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), false));
		map.put("businessName", BC.getBusinessName());
		return map;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:16:02
	 *
	 * @param clazzName
	 * @param actionDir
	 * @return
	 * @throws IOException
	 */
	private Writer getQueryPageActionWriter(String clazzName, Object actionDir) throws IOException {
		String fileName = "QueryPage" + clazzName + "Action.java";
		String destPath = actionDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:16:00
	 *
	 * @param BC
	 * @param lowName
	 * @return
	 * @throws Exception
	 */
	private HashMap<String, Object> getQueryPageActionMap(BusinessContext BC, String lowName) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("name", lowName);
		map.put("upTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), true));
		map.put("lowTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), false));
		map.put("queryIn", BC.getQueryIn());
		map.put("queryOut", BC.getQueryOut());
		map.put("businessName", BC.getBusinessName());
		map.put("queryPageUrl", BC.getQueryPageUrl());
		map.put("prefix", BC.getPrefix());
		String ioName = BC.getQueryOut();
		List<IoFieldVo> list = getGlobalDefineList(ioName);
		map.put("globalDefineList", list);
		return map;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:15:47
	 *
	 * @param clazzName
	 * @param actionDir
	 * @return
	 * @throws IOException
	 */
	private Writer getQueryActionWriter(String clazzName, Object actionDir) throws IOException {
		String fileName = "Query" + clazzName + "Action.java";
		String destPath = actionDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:15:45
	 *
	 * @param BC
	 * @param lowName
	 * @return
	 * @throws Exception
	 */
	private HashMap<String, Object> getQueryActionMap(BusinessContext BC, String lowName) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("name", lowName);
		map.put("upTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), true));
		map.put("lowTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), false));
		map.put("queryIn", BC.getQueryIn());
		map.put("queryOut", BC.getQueryOut());
		map.put("businessName", BC.getBusinessName());
		map.put("queryUrl", BC.getQueryUrl());
		map.put("prefix", BC.getPrefix());
		String ioName = BC.getQueryOut();
		List<IoFieldVo> list = getGlobalDefineList(ioName);
		map.put("globalDefineList", list);
		return map;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:15:35
	 *
	 * @param clazzName
	 * @param actionDir
	 * @return
	 * @throws IOException
	 */
	private Writer getDeleteActionWriter(String clazzName, Object actionDir) throws IOException {
		String fileName = "Delete" + clazzName + "Action.java";
		String destPath = actionDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:15:33
	 *
	 * @param BC
	 * @param lowName
	 * @return
	 */
	private HashMap<String, Object> getDeleteActionMap(BusinessContext BC, String lowName) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("name", lowName);
		map.put("upTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), true));
		map.put("deleteIn", BC.getDeleteIn());
		map.put("businessName", BC.getBusinessName());
		map.put("deleteUrl", BC.getDeleteUrl());
		map.put("prefix", BC.getPrefix());
		return map;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:15:19
	 *
	 * @param clazzName
	 * @param actionDir
	 * @return
	 * @throws IOException
	 */
	private Writer getUpdateActionWriter(String clazzName, Object actionDir) throws IOException {
		String fileName = "Update" + clazzName + "Action.java";
		String destPath = actionDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:15:17
	 *
	 * @param BC
	 * @param lowName
	 * @return
	 */
	private HashMap<String, Object> getUpdateActionMap(BusinessContext BC, String lowName) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("name", lowName);
		map.put("upTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), true));
		map.put("updateIn", BC.getUpdateIn());
		map.put("businessName", BC.getBusinessName());
		map.put("updateUrl", BC.getUpdateUrl());
		map.put("prefix", BC.getPrefix());
		return map;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午4:04:52
	 *
	 * @param clazzName
	 * @param actionDir
	 * @return
	 * @throws IOException
	 */
	private Writer getAddActionWriter(String clazzName, Object actionDir) throws IOException {
		String fileName = "Add" + clazzName + "Action.java";
		String destPath = actionDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @param lowName
	 * @DESCRIBE
	 * @DATE 2018年7月9日 下午3:48:15
	 *
	 * @param context
	 * @return
	 * @throws Exception
	 */
	private HashMap<String, Object> getAddActionMap(BusinessContext BC, String lowName) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("pkg", BC.getPkg());
		map.put("name", lowName);
		map.put("prefix", BC.getPrefix());
		map.put("upTumTabNam", StringUtils.transferToHumpName(BC.getTabNam(), true));
		map.put("addIn", BC.getAddIn());
		map.put("businessName", BC.getBusinessName());
		map.put("addUrl", BC.getAddUrl());
		map.put("prefix", BC.getPrefix());
		return map;
	}

	/**
	 * 
	 * @DESCRIBE
	 * @DATE 2018年7月10日 下午3:35:58
	 *
	 * @param ioName
	 * @return
	 * @throws Exception
	 */
	private List<IoFieldVo> getGlobalDefineList(String ioName) throws Exception {
		String ioFile = context.getIoDir();
		ioFile = ioFile + "\\" + ioName + ".json";
		String ioJson = FileUtils.readFile(ioFile, "utf-8");
		JSONArray ja = JSON.parseArray(ioJson);
		List<IoFieldVo> list = new ArrayList<>();
		for (Object object : ja) {
			JSONObject jo = (JSONObject) object;
			if (jo.getString("globalDefine") != null && "".equals(jo.getString("globalDefine")) == false) {
				IoFieldVo vo = new IoFieldVo();
				vo.setIoName(ioName);
				vo.setJavaType(jo.getString("javaType"));
				String fieldName = jo.getString("fieldName");
				vo.setLowJavaName(fieldName);
				String upName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				vo.setUpJavaName(upName);
				vo.setChnName(jo.getString("chnName"));
				vo.setGlobalDefine(jo.getString("globalDefine"));
				list.add(vo);
			}
		}
		return list;
	}

	public static void main(String[] args) throws AppException {
		BusinessContext context = new BusinessContext();
		Properties prop = null;
		try {
			prop = PropertyUtils.getSysPropFromRoot();
		} catch (IOException e) {
			throw new AppException("", e);
		}
		context.setPkg(prop.getProperty("PACKAGE"));
		context.setTemplateDir(prop.getProperty("TEMPLATE"));
		context.setIoDir(prop.getProperty("IO_DIR"));
		context.setDestDir(prop.getProperty("DIR"));

		context.setUrl(prop.getProperty("URL"));
		context.setDriver(prop.getProperty("DRIVER"));
		context.setName(prop.getProperty("USER"));
		context.setPwd(prop.getProperty("PWD"));

		context.setTabNam(prop.getProperty("TABLE_NAME"));
		context.setPrefix(prop.getProperty("PREFIX"));
		context.setBusinessName(prop.getProperty("BUSINESS_NAME"));
		context.setAddIn(prop.getProperty("ADD_IN"));
		context.setAddUrl(prop.getProperty("ADD_URL"));
		context.setUpdateIn(prop.getProperty("UPDATE_IN"));
		context.setUpdateUrl(prop.getProperty("UPDATE_URL"));
		context.setDeleteIn(prop.getProperty("DELETE_IN"));
		context.setDeleteUrl(prop.getProperty("DELETE_URL"));
		context.setQueryIn(prop.getProperty("QUERY_IN"));
		context.setQueryOut(prop.getProperty("QUERY_OUT"));
		context.setQueryUrl(prop.getProperty("QUERY_URL"));
		context.setQueryPageUrl(prop.getProperty("QUERY_PAGE_URL"));
		CodeGenerator genr = new BusinessCodeGenerator(context);
		genr.generate();
	}
}
